package org.boulderfoodrescue.webapp.server.timeSlots;

import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.logging.Logger;

import org.boulderfoodrescue.webapp.shared.RecurringEvent;

import com.google.appengine.api.datastore.DatastoreService;
import com.google.appengine.api.datastore.DatastoreServiceFactory;
import com.google.appengine.api.datastore.Entity;
import com.google.appengine.api.datastore.EntityNotFoundException;
import com.google.appengine.api.datastore.FetchOptions;
import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.KeyFactory;
import com.google.appengine.api.datastore.Query;
import com.google.appengine.api.datastore.Query.FilterOperator;

public class RecurringEventDatabase {
	private static final Logger log = Logger.getLogger(RecurringEventDatabase.class.getName());

	public static RecurringEvent addRecurringEvent(RecurringEvent event)
	{
		DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
		Entity databaseOneTimeEvent = recurringEventToEntity(event);
		Long key = datastore.put(databaseOneTimeEvent).getId();
		event.setDatabaseKey(key);
		log.info("New recurring event added to datbase");
		return event;
	}
	
	public static RecurringEvent updateRecurringEvent(RecurringEvent event){
		Long key = null;
		DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
		key = datastore.put(recurringEventToEntity(event)).getId();
		event.setDatabaseKey(key);
		return event;
	}

	public static RecurringEvent getRecurringEvent(Long databaseKey){
		DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
		Key key = KeyFactory.createKey("recurringEvent", databaseKey);
		Entity entity;
		try {
			entity = datastore.get(key);
		} catch (EntityNotFoundException e) {
			log.warning("Recurring event not found in database");
			return null;
		}
		RecurringEvent re = entityToRecurringEvent(entity);
		return re;
	}
	
	public static List<RecurringEvent> getRecurringEvents(Long locationKey, int maxNumberToReturn){
		Query query = new Query("recurringEvent");
		query.addFilter("locationKey", FilterOperator.EQUAL, locationKey);
		
		return queryRecurringEventDatabase(query, maxNumberToReturn);
	}
	
	private static List<RecurringEvent> queryRecurringEventDatabase(Query query, int maxNumberToReturn)
	{
		List<RecurringEvent> events = new LinkedList<RecurringEvent>();
		DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
		
		List<Entity> dEvents = datastore.prepare(query).asList(FetchOptions.Builder.withLimit(maxNumberToReturn));
		
		for(Entity dEvent : dEvents)
		{
			RecurringEvent event = entityToRecurringEvent(dEvent);
			events.add(event);
		}
		log.info("Retrieved recurring event info for "+events.size()+" events.");
		return events;
	}

	public static Boolean removeRecurringEvent(RecurringEvent event)
	{
		DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
		Entity databaseUser = new Entity("recurringEvent", event.getDatabaseKey());
		datastore.delete(databaseUser.getKey());
		return true;
	}
	
	private static Entity recurringEventToEntity(RecurringEvent event)
	{
		Entity databaseRecurringEvent;
		if(event.getDatabaseKey() != null && event.getDatabaseKey() != 0)
			databaseRecurringEvent = new Entity("recurringEvent", event.getDatabaseKey());
		else
			databaseRecurringEvent = new Entity("recurringEvent");
		databaseRecurringEvent.setProperty("dayOfMonth", event.getDayOfMonth());
		databaseRecurringEvent.setProperty("endDate", event.getEndDate());
		databaseRecurringEvent.setProperty("endTime", event.getEndTime());
		databaseRecurringEvent.setProperty("endType", event.getEndTypeAsLong());
		databaseRecurringEvent.setProperty("frequency", event.getFrequency());
		databaseRecurringEvent.setProperty("numberOfOccurences", event.getNumberOfOccurences());
		databaseRecurringEvent.setProperty("repeatsOn", event.getRepeatsOn());
		databaseRecurringEvent.setProperty("repeatType", event.getRepeatTypeAsLong());
		databaseRecurringEvent.setProperty("startDate", event.getStartDate());
		databaseRecurringEvent.setProperty("startTime", event.getStartTime());
		databaseRecurringEvent.setProperty("locationKey", event.getLocationKey());
		databaseRecurringEvent.setProperty("allDay", event.getAllDay());
		
		return databaseRecurringEvent;
	}
	
	private static RecurringEvent entityToRecurringEvent(Entity entity)
	{
		RecurringEvent recurringEvent = new RecurringEvent();
		recurringEvent.setDayOfMonth((Boolean) entity.getProperty("dayOfMonth"));
		recurringEvent.setEndDate((Date) entity.getProperty("endDate"));
		recurringEvent.setEndTime((Date) entity.getProperty("endTime"));
		recurringEvent.setEndTypeViaLong((Long) entity.getProperty("endType"));
		recurringEvent.setFrequency((Long) entity.getProperty("frequency"));
		
		//TO DO
		//recurringEvent.setModifiedEventsInSeries(modifiedEventsInSeries)
		
		recurringEvent.setNumberOfOccurences((Long) entity.getProperty("numberOfOccurences"));
		recurringEvent.setRepeatsOn((String) entity.getProperty("repeatsOn"));
		recurringEvent.setRepeatTypeViaLong((Long) entity.getProperty("repeatType"));
		recurringEvent.setStartDate((Date) entity.getProperty("startDate"));
		recurringEvent.setStartTime((Date) entity.getProperty("startTime"));
		recurringEvent.setLocationKey((Long) entity.getProperty("locationKey"));
		recurringEvent.setAllDay((Boolean) entity.getProperty("allDay"));
		recurringEvent.setDatabaseKey(entity.getKey().getId());
		
		return recurringEvent;
	}
}
